<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <base data-ice="baseUrl" href="../../">
  <title data-ice="title">src/cLive2DApp.js | live2d-widget.js</title>
  <link type="text/css" rel="stylesheet" href="css/style.css">
  <link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
  <script src="script/prettify/prettify.js"></script>
  <script src="script/manual.js"></script>
<meta name="description" content="Add the Sseexxyyy live2d to webpages."><meta property="twitter:card" content="summary"><meta property="twitter:title" content="live2d-widget.js"><meta property="twitter:description" content="Add the Sseexxyyy live2d to webpages."></head>
<body class="layout-container" data-ice="rootContainer">

<header>
  <a href="./">Home</a>
  
  <a href="identifiers.html">Reference</a>
  <a href="source.html">Source</a>
  
  <div class="search-box">
  <span>
    <img src="./image/search.png">
    <span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
  </span>
    <ul class="search-result"></ul>
  </div>
<a style="position:relative; top:3px;" href="https://github.com/xiazeyu/live2d-widget.js"><img width="20px" src="./image/github.png"></a></header>

<nav class="navigation" data-ice="nav"><div>
  <ul>
    
  <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/index.js~L2Dwidget.html">L2Dwidget</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-PlatformManager">PlatformManager</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-captureFrame">captureFrame</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-theRealInit">theRealInit</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-cManager">cManager</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-cModel">cModel</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-createElement">createElement</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-getCurrentPath">getCurrentPath</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-cDefine">cDefine</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-variable">V</span><span data-ice="name"><span><a href="variable/index.html#static-variable-currWebGL">currWebGL</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#config">config</a><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-configApplyer">configApplyer</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib">lib</a><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-EYE_STATE">EYE_STATE</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DBaseModel">L2DBaseModel</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DExpressionMotion">L2DExpressionMotion</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DExpressionParam">L2DExpressionParam</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DEyeBlink">L2DEyeBlink</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DMatrix44">L2DMatrix44</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DModelMatrix">L2DModelMatrix</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DMotionManager">L2DMotionManager</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DPartsParam">L2DPartsParam</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DPhysics">L2DPhysics</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DPose">L2DPose</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DTargetPoint">L2DTargetPoint</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-L2DViewMatrix">L2DViewMatrix</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-Live2DFramework">Live2DFramework</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#utils">utils</a><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-MatrixStack">MatrixStack</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-ModelSettingJson">ModelSettingJson</a></span></span></li>
</ul>
</div>
</nav>

<div class="content" data-ice="content"><h1 data-ice="title">src/cLive2DApp.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">/**
 * @description The main part of live2d-widget
 */


import { config } from &apos;./config/configMgr&apos;;
import { createElement, currWebGL, currCanvas } from &apos;./elementMgr&apos;;
import { UtSystem,
         UtDebug,
         LDTransform,
         LDGL,
         Live2D,
         Live2DModelWebGL,
         Live2DModelJS,
         Live2DMotion,
         MotionQueueManager,
         PhysicsHair,
         AMotion,
         PartsDataID,
         DrawDataID,
         BaseDataID,
         ParamID } from &apos;./lib/live2d.core&apos;;
import { L2DTargetPoint, L2DViewMatrix, L2DMatrix44 } from &quot;./lib/Live2DFramework&quot;;
import { cManager } from &quot;./cManager&quot;;
import { MatrixStack } from &quot;./utils/MatrixStack&quot;;
import { cDefine } from &quot;./cDefine&quot;;
import device from &apos;current-device&apos;;

let live2DMgr = null;
let captureFrameCB = undefined;
let isDrawStart = false;
let dragMgr = null;
let viewMatrix = null;
let projMatrix = null;
let deviceToScreen = null;
let drag = false;
let lastMouseX = 0;
let lastMouseY = 0;
let headPos = 0.5;
let opacityDefault = 0.7;
let opacityHover = 1;
let eventemitter = null;


/**
 * Main function of live2d-widget
 * @return {null}
 */

function theRealInit (emitter){

  createElement();
  initEvent();

  live2DMgr = new cManager(eventemitter)
  dragMgr = new L2DTargetPoint();
  let rect = currCanvas.getBoundingClientRect();
  let ratio = rect.height / rect.width;
  let left = cDefine.VIEW_LOGICAL_LEFT;
  let right = cDefine.VIEW_LOGICAL_RIGHT;
  let bottom = -ratio;
  let top = ratio;

  viewMatrix = new L2DViewMatrix();

  viewMatrix.setScreenRect(left, right, bottom, top);

  viewMatrix.setMaxScreenRect(cDefine.VIEW_LOGICAL_MAX_LEFT,
    cDefine.VIEW_LOGICAL_MAX_RIGHT,
    cDefine.VIEW_LOGICAL_MAX_BOTTOM,
    cDefine.VIEW_LOGICAL_MAX_TOP);

  modelScaling(device.mobile() &amp;&amp; config.mobile.scale || config.model.scale)

  projMatrix = new L2DMatrix44();
  projMatrix.multScale(1, (rect.width / rect.height));

  deviceToScreen = new L2DMatrix44();
  deviceToScreen.multTranslate(-rect.width / 2.0, -rect.height / 2.0);  // #32
  deviceToScreen.multScale(2 / rect.width, -2 / rect.height);  // #32


  Live2D.setGL(currWebGL);
  currWebGL.clearColor(0.0, 0.0, 0.0, 0.0);
  changeModel(config.model.jsonPath);
  startDraw();


}

/**
 * Capture current frame to png file
 * @param  {Function} callback The callback function which will receive the current frame
 * @return {null}
 * @example
 * You can use codes below to let the user download the current frame
 *
 * L2Dwidget.captureFrame(
 *   function(e){
 *     let link = document.createElement(&apos;a&apos;);
 *     document.body.appendChild(link);
 *     link.setAttribute(&apos;type&apos;, &apos;hidden&apos;);
 *     link.href = e;
 *     link.download = &apos;live2d.png&apos;;
 *     link.click();
 *   }
 * );
 *
 * @description Thanks to @journey-ad https://github.com/journey-ad/live2d_src/commit/97356a19f93d2abd83966f032a53b5ca1109fbc3
 */

function captureFrame(callback){
  captureFrameCB = callback;
}

function initEvent(){
  if (currCanvas.addEventListener) {
    window.addEventListener(&quot;click&quot;, mouseEvent);
    window.addEventListener(&quot;mousedown&quot;, mouseEvent);
    window.addEventListener(&quot;mousemove&quot;, mouseEvent);
    window.addEventListener(&quot;mouseup&quot;, mouseEvent);
    document.addEventListener(&quot;mouseleave&quot;, mouseEvent);
    window.addEventListener(&quot;touchstart&quot;, touchEvent);
    window.addEventListener(&quot;touchend&quot;, touchEvent);
    window.addEventListener(&quot;touchmove&quot;, touchEvent);
  }
}

function startDraw() {
  if (!isDrawStart) {
    isDrawStart = true;
    (function tick() {
      draw();
      let requestAnimationFrame =
        window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame;

      requestAnimationFrame(tick, currCanvas);
      if(captureFrameCB !== undefined){
        captureFrameCB(currCanvas.toDataURL());
        captureFrameCB = undefined;
      }
    })();
  }
}

function draw()
{
    MatrixStack.reset();
    MatrixStack.loadIdentity();
    dragMgr.update();
    live2DMgr.setDrag(dragMgr.getX(), dragMgr.getY());

    currWebGL.clear(currWebGL.COLOR_BUFFER_BIT);

    MatrixStack.multMatrix(projMatrix.getArray());
    MatrixStack.multMatrix(viewMatrix.getArray());
    MatrixStack.push();

    for (let i = 0; i &lt; live2DMgr.numModels(); i++)
    {
        let model = live2DMgr.getModel(i);

        if(model == null) return;

        if (model.initialized &amp;&amp; !model.updating)
        {
            model.update();
            model.draw(currWebGL);
        }
    }
    MatrixStack.pop();
}

function changeModel(modelurl) // &#x66F4;&#x6362;&#x6A21;&#x578B;
{
    live2DMgr.reloadFlg = true;
    live2DMgr.count++; // &#x73B0;&#x5728;&#x4ECD;&#x6709;&#x591A;&#x6A21;&#x578B;&#x652F;&#x6301;&#xFF0C;&#x7A0D;&#x540E;&#x53EF;&#x4EE5;&#x7CBE;&#x7B80;
    live2DMgr.changeModel(currWebGL, modelurl);
}

function modelScaling(scale) {
  viewMatrix.adjustScale(0, 0, scale);
}
/*
function transformRange(center, transform, range)
{
    let a = {
        x: transform.x - center.x,
        y: transform.y - center.y
    }
    let r = Math.sqrt(Math.pow(a.x,2) + Math.pow(a.y,2));
    if (r &gt; range) {
        a = {
            x: a.x / r * range + center.x,
            y: a.y / r * range + center.y
        };
        return a;
    } else {
        return transform;
    }
}
*/
function dot(A,B)
{
    return A.x * B.x + A.y * B.y;
}

function normalize(x,y)
{
    let length = Math.sqrt(x * x + y * y)
    return {
        x: x / length,
        y: y / length
    }
}

function transformRect(center, transform, rect)
{
    if (transform.x &lt; rect.left + rect.width &amp;&amp; transform.y &lt; rect.top + rect.height &amp;&amp;
        transform.x &gt; rect.left &amp;&amp; transform.y &gt; rect.top) return transform;
    let Len_X = center.x - transform.x;
    let Len_Y = center.y - transform.y;

    function angle(Len_X, Len_Y)
    {
        return Math.acos(dot({
            x: 0,
            y: 1
        }, normalize(Len_X, Len_Y))) * 180 / Math.PI
    }

    let angleTarget = angle(Len_X, Len_Y);
    if (transform.x &lt; center.x) angleTarget = 360 - angleTarget;
    let angleLeftTop = 360 - angle(rect.left - center.x, (rect.top - center.y) * -1);
    let angleLeftBottom = 360 - angle(rect.left - center.x, (rect.top + rect.height - center.y) * -1);
    let angleRightTop = angle(rect.left + rect.width - center.x, (rect.top - center.y) * -1);
    let angleRightBottom = angle(rect.left + rect.width - center.x, (rect.top + rect.height - center.y) * -1);
    let scale = Len_Y / Len_X;
    let res = {};

    if (angleTarget &lt; angleRightTop) {
        let y3 = rect.top - center.y;
        let x3 = y3 / scale;
        res = {
            y: center.y + y3,
            x: center.x + x3
        }
    } else if(angleTarget &lt; angleRightBottom) {
        let x3 = rect.left + rect.width - center.x;
        let y3 = x3 * scale;
        res = {
            y: center.y + y3,
            x: center.x + x3
        }
    } else if (angleTarget &lt; angleLeftBottom) {
        let y3 = rect.top + rect.height - center.y;
        let x3 = y3 / scale;
        res = {
            y: center.y + y3,
            x: center.x + x3
        }
    } else if (angleTarget &lt; angleLeftTop) {
        let x3 = center.x - rect.left;
        let y3 = x3 * scale;
        res = {
            y: center.y - y3,
            x: center.x - x3
        }
    } else {
        let y3 = rect.top - center.y;
        let x3 = y3 / scale;
        res = {
            y: center.y + y3,
            x: center.x + x3
        }
    }

    return res;
}

function modelTurnHead(event)
{
    drag = true;

    let rect = currCanvas.getBoundingClientRect();

    let sx = transformScreenX(event.clientX - rect.left);
    let sy = transformScreenY(event.clientY - rect.top);
    let target = transformRect({
        x: rect.left + rect.width / 2,
        y: rect.top + rect.height * headPos
    }, {
        x: event.clientX,
        y: event.clientY
    }, rect)
    let vx = transformViewX(target.x - rect.left);
    let vy = transformViewY(target.y - rect.top);

    if (cDefine.DEBUG_MOUSE_LOG)
        console.log(&quot;modelTurnHead onMouseMove device( x:&quot; + event.clientX + &quot; y:&quot; + event.clientY + &quot; ) view( x:&quot; + vx + &quot; y:&quot; + vy + &quot;)&quot;);

    lastMouseX = sx;
    lastMouseY = sy;

    dragMgr.setPoint(vx, vy);
}

function modelTapEvent(event)
{
    drag = true;

    let rect = currCanvas.getBoundingClientRect();

    let sx = transformScreenX(event.clientX - rect.left);
    let sy = transformScreenY(event.clientY - rect.top);
    let target = transformRect({
        x: rect.left + rect.width / 2,
        y: rect.top + rect.height * headPos
    }, {
        x: event.clientX,
        y: event.clientY
    }, rect)
    let vx = transformViewX(target.x - rect.left);
    let vy = transformViewY(target.y - rect.top);

    if (cDefine.DEBUG_MOUSE_LOG)
        console.log(&quot;modelTapEvent onMouseDown device( x:&quot; + event.clientX + &quot; y:&quot; + event.clientY + &quot; ) view( x:&quot; + vx + &quot; y:&quot; + vy + &quot;)&quot;);

    lastMouseX = sx;
    lastMouseY = sy;

    eventemitter.emit(&apos;tap&apos;, event);

    live2DMgr.tapEvent(vx, vy);
}

function followPointer(event)
{
    let rect = currCanvas.getBoundingClientRect();

    let sx = transformScreenX(event.clientX - rect.left);
    let sy = transformScreenY(event.clientY - rect.top);

    // log but seems ok
    // console.log(&quot;ecx=&quot; + event.clientX + &quot; ecy=&quot; + event.clientY + &quot; sx=&quot; + sx + &quot; sy=&quot; + sy);

    let target = transformRect({// seems ok here
        x: rect.left + rect.width / 2,
        y: rect.top + rect.height * headPos
    }, {
        x: event.clientX,
        y: event.clientY
    }, rect)
    let vx = transformViewX(target.x - rect.left);
    let vy = transformViewY(target.y - rect.top);

    if (cDefine.DEBUG_MOUSE_LOG)
        console.log(&quot;followPointer onMouseMove device( x:&quot; + event.clientX + &quot; y:&quot; + event.clientY + &quot; ) view( x:&quot; + vx + &quot; y:&quot; + vy + &quot;)&quot;);

    if (drag)
    {
        lastMouseX = sx;
        lastMouseY = sy;
        dragMgr.setPoint(vx, vy);
    }
}

function lookFront()
{
    if (drag) {
        drag = false;
    }
    dragMgr.setPoint(0, 0);
}

function mouseEvent(e)
{
    //e.preventDefault();
    if (e.type == &quot;mousedown&quot;) {
        modelTapEvent(e);
    } else if (e.type == &quot;mousemove&quot;) {
        modelTurnHead(e);
    } else if (e.type == &quot;mouseup&quot;) {
        if(&quot;button&quot; in e &amp;&amp; e.button != 0) return;
        // lookFront();
    } else if (e.type == &quot;mouseleave&quot;) {
        lookFront();
    }
}

function touchEvent(e)
{
    var touch = e.touches[0];
    if (e.type == &quot;touchstart&quot;) {
        if (e.touches.length == 1) modelTapEvent(touch);
        // onClick(touch);
    } else if (e.type == &quot;touchmove&quot;) {
        followPointer(touch);
    } else if (e.type == &quot;touchend&quot;) {
        lookFront();
    }
}

function transformViewX(deviceX)
{
    var screenX = deviceToScreen.transformX(deviceX);
    return viewMatrix.invertTransformX(screenX);
}


function transformViewY(deviceY)
{
    var screenY = deviceToScreen.transformY(deviceY);
    return viewMatrix.invertTransformY(screenY);
}


function transformScreenX(deviceX)
{
    return deviceToScreen.transformX(deviceX);
}


function transformScreenY(deviceY)
{
    return deviceToScreen.transformY(deviceY);
}

export{
  theRealInit,
  captureFrame,
}
</code></pre>

</div>

<footer class="footer">
  Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>

<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>
